#include "tick.h"
#include <errno.h>
#include <stdio.h>
#include <memory.h>
#include <time.h>
#ifdef _LINUX_
#include <malloc.h>
#endif

#ifdef _MACOS_
#include <stdlib.h>
#endif


static char *convert_ftime_to_str(double ftime, char *buf) {
  time_t t = (time_t)(ftime);
  struct tm tt;
  localtime_r(&t, &tt);
  snprintf(buf, 64, "%04d-%02d-%02d %02d:%02d:%02d", tt.tm_year + 1900,
           tt.tm_mon + 1, tt.tm_mday, tt.tm_hour, tt.tm_min, tt.tm_sec);
  return buf;
}

TICK_DATA load_all_tick_bin(const char* filepath, size_t* size) {
  int ret = 0;
  FILE *fp = fopen(filepath, "rb");
  if (fp == NULL) {
    printf("Can not open tick data %s, err %d\n", filepath, errno);
    ret = -1000;
  }

  TICK_DATA td = NULL;
  #ifdef _LINUX_
  off64_t ofe = 0;
  #endif
  #ifdef _MACOS_
  off_t ofe = 0;
  #endif
  size_t all = 0;
  if (!ret) {
  #ifdef _LINUX_
    fseeko64(fp, 0, SEEK_END);
    ofe = ftello64(fp);
  #endif
  #ifdef _MACOS_
    fseeko(fp, 0, SEEK_END);
    ofe = ftello(fp);
  #endif
    if (0 != ((uint64_t)(ofe) % sizeof(Tick))) {
      ret = -1001;
    }
  }

  if (!ret) {
    all = (uint64_t)(ofe) / sizeof(Tick);

    td = malloc(sizeof(Tick) * all);
    // set the start position
  #ifdef _LINUX_
    fseeko64(fp, 0, SEEK_SET);
  #endif
  #ifdef _MACOS_
    fseeko(fp, 0, SEEK_SET);
  #endif


    size_t readed = fread(td, sizeof(Tick), all, fp);
    if (all != readed) {
      printf("data size is %lu, but read %ld from %s\n", all, readed, filepath);
      ret = -1002;
    } else {
      *size = all;
    }
  }

  if (fp != NULL)
    fclose(fp);

  if (!ret) {
    char buf1[64], buf2[64];
    printf("all size %ld, read %lu\n    Start %.02lf to %.02lf ==> %s to %s\n",
           all, *size, td[0].ftime, td[all - 1].ftime,
           convert_ftime_to_str(td[0].ftime, buf1),
           convert_ftime_to_str(td[all - 1].ftime, buf2));
  }

  if (ret) {
    printf("error %d\n", ret);
    if (td != NULL)
      free(td);
    td = NULL;
  }

  return td;
}

TICK_DATA load_tick_bin(const char *filepath, size_t *size, const int64_t spos,
                        const int64_t epos) {
  int ret = 0;
  FILE *fp = fopen(filepath, "rb");
  if (fp == NULL) {
    printf("Can not open tick data %s, err %d\n", filepath, errno);
    ret = -1000;
  }

  TICK_DATA td = NULL;
  #ifdef _LINUX_
  off64_t ofe = 0;
  #endif
  #ifdef _MACOS_
  off_t ofe = 0;
  #endif

  size_t all = 0;
  int64_t s = spos;
  int64_t e = epos;
  size_t len = 0;
  if (!ret) {
    #ifdef _LINUX_
    fseeko64(fp, 0, SEEK_END);
    #endif
    #ifdef _MACOS_
    fseeko(fp, 0, SEEK_END);
    #endif

    ofe = ftello(fp);
    if (0 != ((uint64_t)(ofe) % sizeof(Tick)))
      ret = -1001;
  }

  if (!ret) {
    all = (uint64_t)(ofe) / sizeof(Tick);

    if (s < 2099200)
      s = 2099200;
    if ((e <= s) || (e >= all))
      e = all - 1;

    len = e - s + 1;
    // alloc buffer
    td = malloc(sizeof(Tick) * len);
    // set the start position
    #ifdef _LINUX_
      fseeko64(fp, s * sizeof(Tick), SEEK_SET);
    #endif
    #ifdef _MACOS_
      fseeko(fp, s * sizeof(Tick), SEEK_SET);
    #endif

    size_t readed = fread(td, sizeof(Tick), len, fp);
    if (len != readed) {
      printf("data size is %lu, but read %ld from %s\n", len, readed, filepath);
      ret = -1002;
    } else {
      *size = len;
    }
  }

  if (fp != NULL)
    fclose(fp);

  if (!ret) {
    char buf1[64], buf2[64];
    printf("all size %ld, read %lu\n    Start %.02lf to %.02lf ==> %s to %s\n",
           all, *size, td[0].ftime, td[len - 1].ftime,
           convert_ftime_to_str(td[0].ftime, buf1),
           convert_ftime_to_str(td[len - 1].ftime, buf2));
  }

  if (ret) {
    printf("error %d\n", ret);
    if (td != NULL)
      free(td);
    td = NULL;
  }

  return td;
}
